agentmux_srv\backend\storage/
muxbus.rs

1// Copyright 2026, AgentMux Corp.
2// SPDX-License-Identifier: Apache-2.0
3
4use rusqlite::params;
5
6use super::error::StoreError;
7use super::store::Store;
8
9#[derive(Debug, Clone, Default)]
10pub struct MuxBusCredentials {
11    pub cognito_domain: String,
12    pub client_id: String,
13    pub access_token: String,
14    pub refresh_token: String,
15    pub id_token: String,
16    pub expires_at: i64,
17    pub user_email: String,
18    pub user_sub: String,
19}
20
21impl MuxBusCredentials {
22    fn now_secs() -> i64 {
23        std::time::SystemTime::now()
24            .duration_since(std::time::UNIX_EPOCH)
25            .unwrap_or_default()
26            .as_secs() as i64
27    }
28
29    pub fn is_valid(&self) -> bool {
30        !self.access_token.is_empty() && self.expires_at > Self::now_secs()
31    }
32
33    pub fn nearly_expired(&self) -> bool {
34        !self.access_token.is_empty() && self.expires_at - Self::now_secs() < 300
35    }
36}
37
38impl Store {
39    pub fn muxbus_load(&self) -> Result<Option<MuxBusCredentials>, StoreError> {
40        let conn = self.conn.lock().unwrap();
41        let mut stmt = conn.prepare(
42            "SELECT cognito_domain, client_id, access_token, refresh_token, id_token,
43                    expires_at, user_email, user_sub
44             FROM db_muxbus_credentials WHERE id = 'global'",
45        )?;
46        match stmt.query_row([], |row| {
47            Ok(MuxBusCredentials {
48                cognito_domain: row.get(0)?,
49                client_id: row.get(1)?,
50                access_token: row.get(2)?,
51                refresh_token: row.get(3)?,
52                id_token: row.get(4)?,
53                expires_at: row.get(5)?,
54                user_email: row.get(6)?,
55                user_sub: row.get(7)?,
56            })
57        }) {
58            Ok(c) => Ok(Some(c)),
59            Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None),
60            Err(e) => Err(e.into()),
61        }
62    }
63
64    pub fn muxbus_save(&self, creds: &MuxBusCredentials) -> Result<(), StoreError> {
65        let conn = self.conn.lock().unwrap();
66        conn.execute(
67            "INSERT OR REPLACE INTO db_muxbus_credentials
68                 (id, cognito_domain, client_id, access_token, refresh_token, id_token,
69                  expires_at, user_email, user_sub)
70             VALUES ('global', ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)",
71            params![
72                creds.cognito_domain,
73                creds.client_id,
74                creds.access_token,
75                creds.refresh_token,
76                creds.id_token,
77                creds.expires_at,
78                creds.user_email,
79                creds.user_sub,
80            ],
81        )?;
82        Ok(())
83    }
84
85    pub fn muxbus_clear(&self) -> Result<(), StoreError> {
86        let conn = self.conn.lock().unwrap();
87        conn.execute("DELETE FROM db_muxbus_credentials WHERE id = 'global'", [])?;
88        Ok(())
89    }
90}